/*
	Copyright 2008, 2009, 2010 Brightworks, Inc.
	
	This file is part of Language Mentor.
	
	Language Mentor is free software: you can redistribute it and/or modify
	it under the terms of the GNU General Public License as published by
	the Free Software Foundation, either version 3 of the License, or
	(at your option) any later version.
	
	Language Mentor is distributed in the hope that it will be useful,
	but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
	GNU General Public License for more details.
	
	You should have received a copy of the GNU General Public License
	along with Language Mentor.  If not, see <http://www.gnu.org/licenses/>.
*/
package com.langcollab.languagementor.controller.audio
{
    import com.brightworks.util.Debug;

    import mx.collections.ArrayCollection;

    public class SequenceStrategy
    {
        public function get currentOrderSpecListIndex():int {return _currentOrderSpecListIndex;}

        protected var _currentOrderSpecListIndex:int = -1;
        protected var _elements:Object;
        protected var _orderSpecList:ArrayCollection = null;

        public function SequenceStrategy():void {}

        // ****************************************************
        //
        //          Public Methods
        //
        // ****************************************************

        public function dispose():void
        {
            _elements = null;
        }

		public function getCurrentElement():AudioSequenceElement
		{
			return _elements[_orderSpecList[_currentOrderSpecListIndex]];
		}
		
        public function getElement(id:Object):AudioSequenceElement
        {
            if (!isElementAllowed(id)) 
				Debug.error_Fatal(["SequenceStrategy.getElement(): passed id not allowed:", id]);
            _currentOrderSpecListIndex = _orderSpecList.getItemIndex(id);
            return getCurrentElement();
        }

        public function getFirstElement():AudioSequenceElement
        {
            reset();
            if (!hasNextOrderSpecListIndexWhereMatchingElementExists()) 
				Debug.error_Fatal("SequenceStrategy.getFirstElement(): no next element - call hasElements() before calling this method");
            return getNextElement();
        }

        public function getNextElement():AudioSequenceElement
        {
            if (!hasNextOrderSpecListIndexWhereMatchingElementExists()) 
				Debug.error_Fatal("SequenceStrategy.getNextElement(): no next element - call hasNextElement() before calling this method");
            iterateToNextOrderSpecListIndexWhereMatchingElementExists();
            return getCurrentElement();
        }

        public function hasElements():Boolean
        {
            for (var i:int = 0; i < (_orderSpecList.length - 1); i++)
            {
                if (_elements.hasOwnProperty(_orderSpecList[i]))
                {
                    return true;
                }
            }
            return false;
        }

        public function hasNextElement():Boolean
        {
            return hasNextOrderSpecListIndexWhereMatchingElementExists();
        }

        public function isElementAllowed(id:Object):Boolean
        {
            if (!_elements.hasOwnProperty(id)) return false;
            if (!_orderSpecList.contains(id))  return false;
            return true;
        }

        public function reset():void
        {
            _currentOrderSpecListIndex = -1;
        }

        // ****************************************************
        //
        //          Private Methods
        //
        // ****************************************************

        private function getNextOrderSpecListIndexWhereMatchingElementExists():int
        {
            for (var i:int = _currentOrderSpecListIndex + 1; i < _orderSpecList.length; i++)
            {
                if (_elements.hasOwnProperty(_orderSpecList[i]))
                {
                    return i;
                }
            }
            return -1;
        }

        private function hasNextOrderSpecListIndexWhereMatchingElementExists():Boolean
        {
            return (getNextOrderSpecListIndexWhereMatchingElementExists() >= 0);
        }

        private function iterateToNextOrderSpecListIndexWhereMatchingElementExists():void
        {
            if (getNextOrderSpecListIndexWhereMatchingElementExists() < 0) 
				Debug.error_Fatal("mx.collections.ArrayCollection.SequenceStrategy.iterateToNextOrderSpecListIndexWhereMatchingElementExists(): call hasNextOrderSpecListIndexWhereMatchingElementExists() before calling this method");
            _currentOrderSpecListIndex = getNextOrderSpecListIndexWhereMatchingElementExists();
        }
   }
}